package com.wande.dataplatform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wande.common.core.exception.ServiceException;
import com.wande.common.mybatis.core.page.PageQuery;
import com.wande.common.mybatis.core.page.TableDataInfo;
import com.wande.dataplatform.common.enums.DataPlatformErrorCode;
import com.wande.dataplatform.domain.Report;
import com.wande.dataplatform.domain.bo.ReportBo;
import com.wande.dataplatform.domain.dto.ChartDataDTO;
import com.wande.dataplatform.domain.vo.ReportVO;
import com.wande.dataplatform.mapper.ReportMapper;
import com.wande.dataplatform.service.IDorisService;
import com.wande.dataplatform.service.IReportService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 报表设计服务实现
 *
 * @author wande
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ReportServiceImpl implements IReportService {

    private final ReportMapper reportMapper;
    private final IDorisService dorisService;

    @Override
    public TableDataInfo<ReportVO> queryPageList(ReportBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Report> wrapper = buildQueryWrapper(bo);
        Page<ReportVO> page = reportMapper.selectVoPage(pageQuery.build(), wrapper);
        return TableDataInfo.build(page);
    }

    @Override
    public List<ReportVO> queryList(ReportBo bo) {
        LambdaQueryWrapper<Report> wrapper = buildQueryWrapper(bo);
        return reportMapper.selectVoList(wrapper);
    }

    private LambdaQueryWrapper<Report> buildQueryWrapper(ReportBo bo) {
        LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(bo.getName()), Report::getName, bo.getName())
            .eq(StrUtil.isNotBlank(bo.getReportType()), Report::getReportType, bo.getReportType())
            .eq(bo.getDatasourceId() != null, Report::getDatasourceId, bo.getDatasourceId())
            .eq(bo.getStatus() != null, Report::getStatus, bo.getStatus())
            .eq(bo.getProjectId() != null, Report::getProjectId, bo.getProjectId())
            .orderByDesc(Report::getCreateTime);
        return wrapper;
    }

    @Override
    public ReportVO queryById(Long id) {
        return reportMapper.selectVoById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(ReportBo bo) {
        Report report = BeanUtil.toBean(bo, Report.class);
        
        // 验证图表配置
        if (StrUtil.isNotBlank(report.getChartConfig())) {
            validateChartConfig(report.getChartConfig());
        }
        
        int rows = reportMapper.insert(report);
        if (rows > 0) {
            bo.setId(report.getId());
        }
        return rows > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(ReportBo bo) {
        Report report = BeanUtil.toBean(bo, Report.class);
        
        // 验证图表配置
        if (StrUtil.isNotBlank(report.getChartConfig())) {
            validateChartConfig(report.getChartConfig());
        }
        
        return reportMapper.updateById(report) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByIds(Collection<Long> ids) {
        return reportMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public ChartDataDTO getChartData(Long reportId, String chartId, Map<String, Object> filters) {
        // 查询报表配置
        ReportVO report = queryById(reportId);
        if (report == null) {
            throw new ServiceException(DataPlatformErrorCode.REPORT_NOT_FOUND.getMessage());
        }

        // 解析图表配置
        if (StrUtil.isBlank(report.getChartConfig())) {
            throw new ServiceException("报表图表配置为空");
        }

        Map<String, Object> chartConfig = JSONUtil.toBean(report.getChartConfig(), Map.class);
        List<Map<String, Object>> charts = (List<Map<String, Object>>) chartConfig.get("charts");
        
        if (CollUtil.isEmpty(charts)) {
            throw new ServiceException("报表图表配置为空");
        }

        // 查找指定图表
        Map<String, Object> targetChart = null;
        for (Map<String, Object> chart : charts) {
            if (chartId.equals(chart.get("id"))) {
                targetChart = chart;
                break;
            }
        }

        if (targetChart == null) {
            throw new ServiceException("图表不存在: " + chartId);
        }

        // 构建查询SQL
        String sql = buildChartSql(targetChart, filters);
        
        // 执行查询
        long startTime = System.currentTimeMillis();
        List<Map<String, Object>> data = dorisService.executeQuery(sql);
        long executeTime = System.currentTimeMillis() - startTime;

        // 构建返回结果
        ChartDataDTO result = new ChartDataDTO();
        result.setChartId(chartId);
        result.setChartType((String) targetChart.get("type"));
        result.setData(data);
        result.setTotal((long) data.size());
        result.setExecuteTime(executeTime);

        // 提取维度和度量
        if (CollUtil.isNotEmpty(data)) {
            Map<String, Object> firstRow = data.get(0);
            result.setDimensions(new ArrayList<>(firstRow.keySet()));
        }

        return result;
    }

    @Override
    public byte[] exportReport(Long reportId, String format) {
        ReportVO report = queryById(reportId);
        if (report == null) {
            throw new ServiceException(DataPlatformErrorCode.REPORT_NOT_FOUND.getMessage());
        }

        // TODO: 实现报表导出功能
        // 根据format类型导出为PDF、Excel或图片
        log.warn("报表导出功能待实现: reportId={}, format={}", reportId, format);
        
        return new byte[0];
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean publishReport(Long id) {
        Report report = reportMapper.selectById(id);
        if (report == null) {
            throw new ServiceException(DataPlatformErrorCode.REPORT_NOT_FOUND.getMessage());
        }

        report.setStatus(1);
        return reportMapper.updateById(report) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean offlineReport(Long id) {
        Report report = reportMapper.selectById(id);
        if (report == null) {
            throw new ServiceException(DataPlatformErrorCode.REPORT_NOT_FOUND.getMessage());
        }

        report.setStatus(0);
        return reportMapper.updateById(report) > 0;
    }

    /**
     * 验证图表配置
     */
    private void validateChartConfig(String chartConfig) {
        try {
            JSONUtil.parseObj(chartConfig);
        } catch (Exception e) {
            throw new ServiceException("图表配置格式错误: " + e.getMessage());
        }
    }

    /**
     * 构建图表查询SQL
     */
    private String buildChartSql(Map<String, Object> chartConfig, Map<String, Object> filters) {
        String sql = (String) chartConfig.get("sql");
        
        if (StrUtil.isBlank(sql)) {
            throw new ServiceException("图表SQL配置为空");
        }

        // 应用过滤条件
        if (filters != null && !filters.isEmpty()) {
            for (Map.Entry<String, Object> entry : filters.entrySet()) {
                String placeholder = "${" + entry.getKey() + "}";
                if (sql.contains(placeholder)) {
                    sql = sql.replace(placeholder, String.valueOf(entry.getValue()));
                }
            }
        }

        return sql;
    }
}
